# Copyright 2001-2007 by iNeed,Inc. All Rights Reserved.
#-*- encoding:utf-8 -*-
"""
the handler for the HTTPRequest  
<h4>{{method}}</h4>
"""
from peer import *
from common import *
import database
import driver,passenger
from django.http import HttpResponse   
from django.template import Template, Context   
from django.shortcuts import render_to_response
__author__  = "Number Huang<huang.bafeng@iNeed.com>"
__status__  = "developing"
__version__ = "0.1111.19.1"
import iNeedCenter
server = iNeedCenter.MsgCenter(centerAddr)
db=database.CreateDB()
cleanDataBaseForTest(db)

import game
import settings
DEMO_WITH_GAME = settings.DEMO_WITH_GAME
#if DEMO_WITH_GAME:
    
    
LOGGIN_TIMEOUT=10     
ENABLE_TTS  = 0x00010000#@android TTS 
ENABLE_RECO = 0x00020000#@android speech recoganize
            
gActiveUserDict =  {}
webLog = getLogger("web",os.path.join(CENTER_LOG_PATH,"web.txt"))
def handleRequest(request,method):
    """
    Dispatch the http request to the peers
    """
    if request.method=="POST":
        data     = request.POST
    else:
        data     = request.GET
    id       = data.get("sessionID")
    #webLog.debug("path=%s,user=%s,agent=%s"%(request.path,id,request.META.get("HTTP_USER_AGENT")))
    try:
        if not gActiveUserDict.has_key(id):
            return render_to_response('login.html', {})
        else:
            if method=="action":
                method=data["action"]
            peer = gActiveUserDict[id]
            func = getattr(peer,method)
            return func(data)
    except:# ETimeout,e:
        logging.exception("fail")
        raise #return HttpResponse("fail")
def mainpage(request):
    return handleRequest(request,"mainpage") 


def login(request):
    #result = "login fail, unknown reason, pls try again"
    if request.method=="GET":#user type /login/ directly
        return render_to_response('login.html', {})
    
    data     = request.POST
    username = data.get("username")
    id = username
    try:
        if not gActiveUserDict.has_key(id):
            
            pwd      = data["password"]
            isDriver = _isDriverTemp(username)#this is only for test
            if isDriver:
                peer = HTMLDriver(username)
            else:
                peer = HTMLPassenger(username)
            
            
            if peer.logIn(username,pwd)==EN_OK:
                gActiveUserDict[id] = peer
                return peer.mainpage(data)
            else:
                pass 
            result =  reporter.result[1]
        else:
            return gActiveUserDict[id].mainpage()
        
    except:# ETimeout,e:
        logging.exception("login fail")
        result = "timeout to login,pls try again"
        
    return HttpResponse(result) 
def showAddService(request):
    return handleRequest(request,"showAddService")

def endTransaction(request):
    return handleRequest(request,"endTransaction")

def publish(request):
    return handleRequest(request,"publish")

def executeOrder(request):
    return handleRequest(request,"executeOrder")

def logout(request):
    
    result = handleRequest(request,"logout")
    
    id = request.session.session_key
    if gActiveUserDict.has_key(id):
        del gActiveUserDict[id]
        
    return result


def updateStatus(request):
    return handleRequest(request,"updateStatus")

def confirm(request):
    return handleRequest(request,"confirm")

def action(request):
    return handleRequest(request,"action")

def comment(request):
    return handleRequest(request,"comment")

ENS_READY_OUT = 0
ENS_READY_GET = 1
ENS_WFR = 2
FilterRequestList=[CSTR_BT,CSTR_ET]
class HTMLPeer(object):
    def __init__(self,phone):
        self.phone = phone
        self.location = [0,0,u"unknown addrss"]
        self.notifyMap={}#{pubID:[info]}
        self.lock= threading.Condition()
        self.counter = 0
        self.gamePeer = None
        self.peerPos = {}#{"peerID":(lat,long,'address')}
    def logIn(self,username,pwd):
        reporter=SyncNonReporter(LOGGIN_TIMEOUT)
        self.peer.logIn(username,pwd,centerID,centerAddr,reporter)
        if DEMO_WITH_GAME and reporter.result[0]==EN_OK:
            self.createGamePeer()
        return reporter.result[0]
    
    def getLocation(self):
        if self.gamePeer:
            return self.gamePeer.getLocation2()
        else:
            return tuple(self.location)
    def getPeerPosition(self,phone):
        
        reporter = Reporter(None,self.handleGPSResponse)
        self.peer.getPeerPos(phone,reporter)
    
    def getPeerPos(self,data):
        """
        Only returns the position data, as few redundant as possible
        """
        phone = self._getPeerIDByPubID(int(data["pubID"]))
        if self.peerPos.has_key(phone):
            params={"latitude":self.peerPos[phone][0],"longitude":self.peerPos[phone][1]}
        else:
            params={}
        self.getPeerPosition(phone)
        self.log.debug("getPeerPos(%d,%d)",self.peerPos[phone][0],self.peerPos[phone][1])
        return render_to_response("getPeerPos.html",params)
    
    def _getPeerIDByPubID(self,pubID):
        order = self.peer.queryService(pubID)
        if self.peer.role==EPR_DRIVER:
            phone = order.orderDict["passengerID"]
        else:
            phone = order.orderDict["driverID"]
        return phone
    def handleGPSResponse(self,retCode,retInfo,extraInfo):
        
        strlist = extraInfo[CSTR2_GPS].splitlines()
        for line1 in strlist:
            if line1.startswith("Location:"):
                    phone = self._getPeerIDByPubID(extraInfo[CSTR2_PUBID])
                    self.peerPos[phone] = getLocation(line1)

    def handleRequest(self,method,info,extraInfo,reporter):
        with AutoLock(self,self.lock): 
            pubID = extraInfo[CSTR2_PUBID]
            if self.notifyMap.has_key(pubID):
                self.log.error("The previous GUI response is still not handled yet_%d_%s"%(pubID,self.notifyMap[pubID][0]))
            else:
                self.log.debug("handleGUIRequest:%d_%s"%(pubID,method))
            if method in FilterRequestList:
                self.handleFilterRequest(method, reporter)
            else:
                timeout = time.time()+extraInfo[CSTR2_TIMEOUT]
                self.notifyMap[pubID] = [method,info,extraInfo,reporter,timeout]
                
            if DEMO_WITH_GAME:
                self.gamePeer.handleRequest(method,info,extraInfo,None)
                
    def handleFilterRequest(self,method,reporter):
        return reporter.notify(EN_OK,retCodeMap[EN_OK])   
             
    def showAddService(self,data):
        params={"sessionID":self.phone}
        return render_to_response('addservice.html', params)    
    
    def confirm(self,data):
        with AutoLock(self,self.lock):    
            
            pubID    = int(data["pubID"])
            #activeIdx= int(data["activeIdx"])
            if self.notifyMap.has_key(pubID):
                #it is possible that if there are 2 clients(same ID) causing the repeated confirm
                msg = self.notifyMap[pubID]#[activeIdx]
                retCode = int(data["retCode"])
                reporter= msg[3]
                #check timeout    
                if time.time()-msg[-1]<0:
                    reporter.notify(retCode,retCodeMap[retCode])
                else:
                    reporter.notify(EN_TIMEOUT,retCodeMap[EN_TIMEOUT])
                del self.notifyMap[pubID]    
                if DEMO_WITH_GAME:
                    self.gamePeer.confirm(msg[0],pubID)
                
            return self.mainpage()
    def _translateContent(self,content):
       
       result=[] 
       for item in translateOrderList:
           if content.has_key(item[0]):
               value = item[2](content[item[0]])#getUStr(
               result.append("%s: %s"%(item[1],value))
       return result
    
    def getNotify(self,data):
        
       with AutoLock(self,self.lock):
            pubID    = int(data["pubID"])
            orderDict = self.peer.queryService(pubID).orderDict
            info     = self._translateContent(orderDict)
            params   = {"info":info,"sessionID":self.phone}
            return render_to_response('confirm.html', params)
            
                
    def updateStatus(self,data):
        
        with AutoLock(self,self.lock):
                     
            self.location = [int(data["longitude"]),int(data["latitude"]),data["address"]]
            self.peer.reportStatus()
            self.counter += 1
            return self.mainpage()#HTTPResponse("nothing")#
                 
    def mainpage(self,data=None):
       
        params=self._checkUpdate()
        params["sessionID"] = self.phone
        params["counter"] = self.counter
        params["curStatus"] = self.peer.status
        params["serviceList"] = self.peer.serviceList
        
        return render_to_response(self.mainhtml, params) 
    
    
        
class HTMLDriver(HTMLPeer):
    def __init__(self,phone):
        super(HTMLDriver,self).__init__(phone)
        name = "driver%s"%phone
        self.log = getLogger("iNeed.%s"%name,os.path.join(DRIVER_LOG_PATH,"%s.txt"%name))
        self.peer = driver.Driver(self)
        self.mainhtml = "driver.html"
        
        
    def createGamePeer(self):
        if DEMO_WITH_GAME:
            self.gamePeer = game.gameActivity.addOneTaxi(None,self.peer)
            
    def executeOrder(self,data):
        pubID = int(data["pubID"])
        order = self.peer.queryService(pubID)
             
        
        if DEMO_WITH_GAME:
            self.gamePeer.executeOrder(order)
                
        self.peer.executeOrder(order)        
        return self.mainpage()
    
    def readyBording(self,data):
        pubID = int(data["pubID"])
        order = self.peer.queryService(pubID)
        reporter = Reporter(None,self.handleRBResponse,RB_TIMEOUT)
        self.peer.notifyBording(order.orderDict["passengerID"],reporter)
        #order.updateStatus(ESE_READY_BT)
        return self.mainpage()
    
    def handleRBResponse(self,retCode,retInfo,extraInfo=None):
        pubID = extraInfo[CSTR2_PUBID]
        if retCode==EN_OK:#TODO,this will be changed to prompt the driver to beginT
            self._transaction(pubID,0)
            
    def _checkUpdate(self):
        
        disableUS = 0
            
        for service in self.peer.serviceList:
            service.action = {} #interact with server
            service.action2= {} #interact with client host
            service.inform = {}
            if service.status==ESE_WF_GUI_CA:
                msg = self.notifyMap[service.pubID]
                method = msg[0]
                service.action["name"]          = "confirm" #"getNotify"#
                service.action["chineseName"]   = u"接受"#translateMethod[method]
                info =  service.getDepartTimeText2()+ u"从"+service.getDepartText2() +\
                                                       u"到" +service.getDestText2()+u"请" + translateMethod[method]
                  
                #service.action["cancel"]       = "cancel" #"getNotify"#
                service.action["cancelName"]   = u"据绝"
                service.inform["msg"] = info   
                service.inform["msgID"]         = service.status|(ENABLE_TTS|ENABLE_RECO)   
                service.action["timeout"] =  msg[2][CSTR2_TIMEOUT]
                    
                disableUS = 1
            elif service.status==ESE_ORDER_DONE: 
                if not service.poolingProcessor or service.poolingProcessor.isMainOrder(service.pubID):#TODO,use a correct logic to represent the
                    service.action2["name"]          = "executeOrder"
                    service.action2["chineseName"]   = u"执行"
                url1 = "/executeOrder/?sessionID=%s&pubID=%d"%(self.phone,service.pubID)
                service.action2["jsFunc"] = "window.location ='%s'"%url1
                #disableUS = 1
            elif service.status==ESE_READY_PICKUP:
                service.action["name"]       = "readyBording"
                service.action["chineseName"]   = u"通知乘客"
                disableUS = 1
                service.inform["msg"] = u"请通知乘客，车已经到达"
            elif service.status==ESE_READY_BT:
                #TODO: add beginT hint,hereing, automatically beginT
                pass
            elif service.status==ESE_TRANSATION_GOING: 
                service.action["name"]          = "endTransaction"
                service.action["chineseName"]   = u"结束交易"
                disableUS = 1    
               
                                                  
        paramDict={"disableUpdateStatus":disableUS}
        return paramDict   
   
    def _transaction(self,pubID,type=0):
        if type==0:
            self.peer.beginTransaction(pubID)
        else:
            self.peer.endTransaction(pubID)
    def beginTransaction(self,data): 
       pubID = int(data["pubID"])
       self._transaction(pubID,0)
       
       return self.mainpage()
    
    def endTransaction(self,data): 
       pubID = int(data["pubID"])
       self._transaction(pubID,1)
       return self.mainpage()       
            
def getLocationByAddress(address):
    return (0,0)
    
class HTMLPassenger(HTMLPeer):
    def __init__(self,phone):
        super(HTMLPassenger,self).__init__(phone)
        name = "Passenger%s"%phone
        self.log = getLogger("iNeed.%s"%name,os.path.join(PASSENGER_LOG_PATH,"%s.txt"%name))
        self.peer = passenger.Passenger(self)
        self.mainhtml = "passenger.html"
        
    def createGamePeer(self): 
        if DEMO_WITH_GAME:
            self.gamePeer = game.gameActivity.addOnePerson(None,self.peer)
    
    def unpublish(self,data): 
       pubID = int(data["pubID"])
       order = self.peer.queryService(pubID)
       self.peer.deleteService(None, order) 
       return self.mainpage()
           
    def publish(self,data):
        paramsDict={}
        if DEMO_WITH_GAME:
            idx = int(data["departureLocation"])
            paramsDict["departureLocation"]   = game.map2Real(game.initPos[0][idx])
            idx = int(data["destinationLocation"])
            paramsDict["destinationLocation"] = game.map2Real(game.endPos[0][idx])
        else:#TODO, the address should use map API to get the real Lat and longt
            location = getLocationByAddress(data["departureLocation"])
            paramsDict["departureLocation"] = (location[0],location[1],"%s"%data["departureLocation"])
            location = getLocationByAddress(data["destinationLocation"])
            paramsDict["destinationLocation"] = (location[0],location[1],"%s"%data["destinationLocation"])
        paramsDict["departureTime"]     = (time.time() + int(data["departureTime"]))
        paramsDict["type"]              = int(data["type"])
        paramsDict["timeout"]           = int(data["timeout"])
       
        #paramsDict["destinationTime"] = None
        #paramsDict["price"] = None
        paramsDict["number"]            = int(data["number"])
        try:
            reporter = SyncNonReporter()
            order = self.peer.addService(reporter,paramsDict)
            if DEMO_WITH_GAME:
                self.gamePeer.activeOrder = order
            #@TODO: process the reporter.result
        except Exception,e:
            self.log.exception("publish fail\nreason: %s"%e)
        return self.mainpage()
   
    
    def comment(self,data): 
       pubID = int(data["pubID"])
       order = self.peer.queryService(pubID)
       params={"score":int(data["score"]),"comment":data["comment"]}
       self.peer.comment(order,params)
       return self.mainpage()
   
    def readyEndTransaction(self,data):
       params ={"pubID": int(data["pubID"])}
       params["sessionID"] = self.phone
       return render_to_response("commentNEnd.html", params) 
    
    def _checkUpdate(self):
        
        disableUS = 0
            
        for service in self.peer.serviceList:
            service.action = {} #interact with server
            service.action2= {} #interact with client host
            #
            if service.status==ESE_WF_GUI_TOGD:
                service.action["name"]          = "unpublish"
                service.action["chineseName"]   = u"知道了"
                info =  u"对不起，没有搜索到可用的出租车，您可以稍后再试"
                service.inform["msg"]       = info
                service.inform["msgID"]     = service.status|(ENABLE_TTS)
                disableUS = 1
            elif service.status==ESE_ORDER_DONE:
                if self.peerPos:
                    service.action2["name"]          = "showPGPS"
                    service.action2["chineseName"]   = u"查看司机位置"
                    phone = service.orderDict["driverID"]
                    onlyOneTime = 0 # if 1, the client will get the position intervally 
                    service.action2["jsFunc"] = "showPeerGPS(%d,%d,%s,%d,%d)"%(self.peerPos[phone][0],self.peerPos[phone][1],self.phone,service.pubID,onlyOneTime)
               
                if service.inform["number"]==0:
                    info =  u"已经为您预订到出租车，祝您出行愉快"
                    service.inform["msg"]       = info
                    service.inform["msgID"]     = service.status|(ENABLE_TTS)
                    service.inform["number"]    = 1
                elif service.inform.has_key("msg"):
                    del service.inform["msg"]
                        
                self.getPeerPosition(service.orderDict["driverID"])
                
            elif service.status==ESE_WF_GUI_RB:
                msg = self.notifyMap[service.pubID]
                service.action["name"]          = "confirm"
                service.action["chineseName"]   = translateMethod[CSTR_RB]
                info =  u"出租车已到达，请确认"
                service.inform["msg"]       = info  
                service.inform["msgID"]     = service.status|(ENABLE_TTS) 
                service.action["timeout"]   = msg[2][CSTR2_TIMEOUT]
                disableUS = 1
            elif service.status==ESE_TRANSATION_GOING: 
                service.action["name"]          = "readyEndTransaction"
                service.action["chineseName"]   = u"评价此次交易"
                disableUS = 1 
            else:
                service.inform = {"number":0}
            
        paramDict={"disableUpdateStatus":disableUS}
        return paramDict    
driverCheckP=re.compile(r"^(\d{2})")
def _isDriverTemp(username):
    m = driverCheckP.match(username)
    id = m.group(1)
    if id=="13":
        return True
    else:
        return False
if __name__=="__main__":
  
    print ESE_WF_GUI_CD&(ENABLE_TTS|ENABLE_RECO)
    